feat(mcp): list_rules tool - #129
Conversation
|
No description provided. |
|
No description provided. |
Enumerate every built-in Plumb rule with id, default severity, and
one-line summary from `Rule::summary`. Sorted by rule id (which encodes
`<category>/<name>`) so the response is deterministic across runs and
independent of `register_builtin` ordering.
Adds `ListRulesArgs` (no fields), `PlumbServer::list_rules` and the
`list_rules_payload` helper, plus the `tools/list` descriptor and
`call_tool` branch. Helper returns `(text, structured)` where
`structured` carries `{ rules: [...], count: N }` and `text` is one
short line per rule — bounded well under the 10 KB token budget.
Unit-tested via the helper (constructing `RequestContext<RoleServer>`
in unit scope is awkward in rmcp 1.5). Stdio protocol coverage and the
`docs/src/mcp.md` table land in a follow-up PR.
Refs #36
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dd945f6 to
3fa0ea6
Compare
|
No description provided. |
|
Now I have everything I need for a complete review of both open PRs. PR #129 —
|
| Location | Severity | Issue |
|---|---|---|
mcp_protocol.rs (missing) |
BLOCKER | No protocol unit tests for get_config — required by mcp-tool-patterns.md (happy path + invalid args) |
lib.rs:~L237 |
Warning | TOCTOU: exists() then metadata() — stat once and match NotFound |
lib.rs (async fn) |
Warning | Blocking fs::metadata / plumb_config::load on async thread — consider spawn_blocking |
dependency-hierarchy.md |
Note | Document doesn't list plumb-cdp or plumb-config under plumb-mcp; update the dep table |
Verdict: REQUEST_CHANGES
|
Conflict resolution attempt blocked. The PR conflicts with main because PR #130 ( |
Merge main containing PR #130 (explain_rule) and PR #131 (lint_url real http URLs) into the list_rules branch. Also resolve doc-only conflict in docs/src/mcp.md. Conflicts in plumb-mcp/src/lib.rs and tests/mcp_protocol.rs are mechanical: both branches added a new tool (`explain_rule` on main, `list_rules` on this branch). The resolution unions both: 4 tools (echo, lint_url, explain_rule, list_rules) registered in list_tools, dispatched in call_tool, and exercised by the test suite. register_builtin import switched to the top-level re-export (plumb_core::register_builtin) introduced on main; the list_rules test now uses the same import rather than the deprecated plumb_core::rules::register_builtin path. Local cargo check skipped — host disk full while syncing toolchain 1.95.0; CI will verify. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Address Claude review REQUEST_CHANGES on PR #129: - Extend `mcp_initialize_and_tools_list` to assert that `list_rules` and `explain_rule` (added on main while this PR was open) are present in the tools/list response. - Add `mcp_list_rules_returns_every_rule` — full JSON-RPC round trip via the binary, asserts isError=false, count>0, and a non-empty rule id on the first entry. - Nit: bind `register_builtin().len()` once in the in-process list_rules test rather than calling the registry twice. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Conflict resolution complete. Merged Also addressed the prior Claude review's REQUEST_CHANGES: added CI: all 13 checks green (Determinism, Preflight, Tests on ubuntu/macos/windows, Coverage, MSRV, cargo-deny, Docs, Size guard, Conventional Commits, Claude review, GitGuardian, action-semantic-pull-request). Latest Claude review verdict for #129 is APPROVE; the trailing REQUEST_CHANGES in the combined verdict comment is scoped to PR #132 ( |
PR #129 (list_rules) merged into main while #132 (get_config) was open. Both tools touched the same MCP server surface in: - crates/plumb-mcp/src/lib.rs (tool registration, call dispatch, args) - crates/plumb-cli/tests/mcp_stdio.rs (tools/list assertion + new test) - docs/src/mcp.md (tool table) Resolution preserves both tools side-by-side: the merged ServerHandler exposes echo, lint_url, explain_rule, list_rules, and get_config. Local cargo check skipped (toolchain install blocked by sandbox disk quota); CI will validate the merge.
Summary
Adds the
list_rulesMCP tool — enumerates every built-in rule with id, default severity, and one-line summary fromRule::summary. Skeleton-scope PR aimed at green CI; protocol-level stdio test coverage anddocs/src/mcp.mdupdates land in a follow-up.Closes #36.
What changed
ListRulesArgsstruct (no fields) +list_rulesasync handler onPlumbServerincrates/plumb-mcp/src/lib.rs.list_toolsand dispatch arm added incall_tool.list_rules_payloadexposes the response shape for unit testing without constructing a fullRequestContext<RoleServer>.<category>/<name>, so categories cluster naturally).content[0], structured payload{rules: [{id, default_severity, summary}], count}instructuredContent,isError: false.Tests
list_rules_returns_every_builtin_rule_sortedincrates/plumb-mcp/tests/mcp_protocol.rs— asserts every registered rule appears, ordering is ascending, and the first entry carries a valid lowercase severity label and a non-empty summary.plumb-mcpandplumb-clistill pass.Out of scope (follow-up)
crates/plumb-cli/tests/mcp_stdio.rsto assertlist_rulesappears intools/list.docs/src/mcp.mdtool table.Plumb invariants honored
#![forbid(unsafe_code)]preserved.unwrap/expect/panic!in library code.plumb-mcpreadsplumb-core::register_builtinonly.Verification
🤖 Generated with Claude Code